﻿using System.Configuration;
using System.IO;
using System.Net.Mail;
using AutoMapper;
using Attachment = Aluetjen.EmailService.Domain.Models.Message.Attachment;
using MailAddress = Aluetjen.EmailService.Domain.Models.Message.MailAddress;
using MailMessage = Aluetjen.EmailService.Domain.Models.Message.MailMessage;

namespace Aluetjen.EmailService.Domain.Gateways
{
    public class SmtpGateway : IGatewayImpl
    {
        private const int DefaultSmtpPort = 25;
        private string _address;
        private int _port;

        static SmtpGateway()
        {
            Mapper.CreateMap<MailMessage, System.Net.Mail.MailMessage>().
                ForMember(x => x.To, t => t.Ignore()).
                ForMember(x => x.ReplyTo, t => t.Ignore()).
                ForMember(x => x.CC, t => t.Ignore()).
                ForMember(x => x.Bcc, t => t.Ignore()).
                ForMember(x => x.AlternateViews, t => t.Ignore()).
                ForMember(x => x.Attachments, t => t.Ignore());

            Mapper.CreateMap<MailAddress, System.Net.Mail.MailAddress>().
                ConstructUsing(src => new System.Net.Mail.MailAddress(src.Address, src.DisplayName));

            Mapper.CreateMap<Attachment, System.Net.Mail.Attachment>().
                ForMember(x => x.ContentType, t => t.Ignore()).
                ForMember(x => x.NameEncoding, t => t.Ignore()).
                ForMember(x => x.ContentId, t => t.Ignore()).
                ForMember(x => x.TransferEncoding, t => t.Ignore()).
                ConstructUsing(src => new System.Net.Mail.Attachment(new MemoryStream(src.Content), src.Name, src.MediaType));
        }

        public void Configure(string connectionString)
        {
            string[] parts = connectionString.Split(':');

            if(parts.Length < 1 || parts.Length > 2)
            {
                ThrowInvalidConnectionString(connectionString);
            }

            _address = parts[0];

            if (parts.Length == 2)
            {
                if(!int.TryParse(parts[1], out _port))
                {
                    ThrowInvalidConnectionString(connectionString);
                }
            }
            else
            {
                _port = DefaultSmtpPort;
            }
        }

        private static void ThrowInvalidConnectionString(string connectionString)
        {
            throw new ConfigurationErrorsException(
                string.Format("The SMTP gateway connection string '{0}' is invalid. " +
                "Specify the host and port of your SMTP Server e.g. 127.0.0.1:25.", connectionString));
        }

        public void Send(MailMessage message)
        {
            var smtpMailMessage = Mapper.Map<MailMessage, System.Net.Mail.MailMessage>(message);

            if (message.To != null)
                message.To.ForEach(i => smtpMailMessage.To.Add(Mapper.Map<MailAddress, System.Net.Mail.MailAddress>(i)));

            if (message.CC != null)
                message.CC.ForEach(i => smtpMailMessage.CC.Add(Mapper.Map<MailAddress, System.Net.Mail.MailAddress>(i)));

            if (message.Bcc != null)
                message.Bcc.ForEach(i => smtpMailMessage.Bcc.Add(Mapper.Map<MailAddress, System.Net.Mail.MailAddress>(i)));

            if (message.Attachments != null)
                message.Attachments.ForEach(i => smtpMailMessage.Attachments.Add(Mapper.Map<Attachment, System.Net.Mail.Attachment>(i)));

            var client = new SmtpClient("127.0.0.1", 25);
            client.Send(smtpMailMessage);
        }
    }
}